<?php
/**
 * $Id: adv_taxonomy_menu.inc,v 1.15 2010/10/21 03:00:26 newzeal Exp $
 * @file adv_taxonomy_menu.inc
 * * @author Jonathan Chaffer   <jchaffer@structureinteractive.com> original taxonomy_menu.module
 * @author Bruno Massa        <http://drupal.org/user/67164> original taxonomy_menu.module
 * @author Kent Parker <kent@webdev.passingphase.co.nz>  adv_taxonomy_menu.module
*   It Generates menu links for all taxonomy terms
 */

/**
 * Admin area. Configure the module, setting which
 * vocabularies will be converted into menus items
 *
 * @return
 *   Array. The form fields.
 */

function theme_adv_taxonomy_menu_admin_item($setting) {
  return '<td>'.$setting->name.'</td><td><a href="'.url('admin/settings/adv_taxonomy_menu').'/edit/'. $setting->tmid .'">edit</a></td><td><a href="'.url('admin/settings/adv_taxonomy_menu').'/delete/'. $setting->tmid .'">delete</a></td>';
}

function _adv_taxonomy_menu_rebuild_form() {
  $form['submit'] = array(
    '#value'          => t('Rebuild Menu'),
    '#type'           => 'submit'
  );
  return $form;
}
function _adv_taxonomy_menu_rebuild_form_submit() {
  menu_rebuild();
  drupal_set_message('The menu has been rebuilt');
}
function theme_adv_taxonomy_menu_admin($array) {
  if(!empty($array)) {
    drupal_add_css(drupal_get_path('module', 'adv_taxonomy_menu') .'/adv_taxonomy_menu.css');
    $output = t('Current available menu systems');
    $output .= '<table id="taxonomy_menu">';
    foreach($array as $item) $output .= '<tr>'.$item.'</tr>';
    $output .= '</table>';
    $output .= drupal_get_form('_adv_taxonomy_menu_rebuild_form');
  }
  else $output = t('There are currently no taxonomy menu systems created');
  return $output;
}

function _adv_taxonomy_menu_admin($op) {
 if($op == 'main') {
  $output = '';
  if($settings = adv_taxonomy_menu_get_settings()) {

    while ($setting = db_fetch_object($settings)) {
 	  $output[] = theme('adv_taxonomy_menu_admin_item', $setting);
    }
  }
  return theme('adv_taxonomy_menu_admin', $output);
 } else {
  if(arg(3)=="delete") {
    if(is_numeric(arg(4))) {
	  $tmid = arg(4);
 	  return adv_taxonomy_menu_delete_form($tmid);
    }
    else $error = "yes";
  }
  if(arg(3)=="edit") {
    if(arg(4)) {
	  $tmid = arg(4);
      if($result = adv_taxonomy_menu_get_settings($tmid)) {
        $settings = db_fetch_object($result);
        $order = unserialize($settings->vocab_order);
      }
      $form['adv_taxonomy_menu_tmid'] = array(
          '#type' => 'hidden',
          '#value' => $tmid,
        );
    }
    else $error = "yes";
  }
  $level = array("not selected");
  $i = 1;
  $num_levels = 0;
  foreach(taxonomy_get_vocabularies() as $vocab) {
	$level[] = $i;
	if($order[$vocab->vid] >0 ) $num_levels++;
    $i++; 
  }
  if(!empty($level)) {
    $form['adv_taxonomy_menu_return'] = array(
      '#value'          => '<a href="'.url('admin/settings/adv_taxonomy_menu').'">Return to main administration page</a>',
      '#type'           => 'markup',
    ); 
    // Create some options for each of the vocabularies
    $form['adv_taxonomy_menu_name'] = array(
      '#default_value'  => $settings->name,
      '#description'    => t('Choose a name to identify the menu system by'),
      '#title'          => t('Name of menu system'),
      '#type'           => 'textfield',
    );
    foreach (taxonomy_get_vocabularies() as $vocab) {
      $form[$vocab->vid] = array(
        '#title'          => $vocab->name,
        '#tree'           => FALSE,
        '#type'           => 'fieldset',
      );
      $form[$vocab->vid]['adv_taxonomy_menu_vocab_order_'. $vocab->vid] = array(
        '#title' => t('Menu Level'),
        '#type' => 'select',
        '#options'        => $level,
        '#default_value'  => $order[$vocab->vid],
        '#description' => t('Enter a number to select the level of this vocabulary in the menu.  If you do not select this vocabulary in the menu then this is ignored.'),
        '#required' => FALSE,
      );

    }
    $options = array(
      ADV_TAXONOMY_MENU_NORMAL  => t('Normal'),
    );
    if (module_exists('views')) {
      $options[ADV_TAXONOMY_MENU_VIEW] = t('Views');
    }
    $form[$vocab->vid]['adv_taxonomy_menu_show'] = array(
      '#default_value'  => isset($settings->show_normal) ? $settings->show_normal : ADV_TAXONOMY_MENU_NORMAL,
      '#options'        => $options,
      '#title'          => t('Default or Views (if enabled)'),
      '#type'           => 'radios',
    );
    if (module_exists('views')) {
	  $form[$vocab->vid]['adv_taxonomy_menu_show']['#description'] = t('When using views you need to create a View with the adv_taxonomy_menu Node ID range filter enabled otherwise the View will not work.  This module uses the default View.  There is no need to enable any other filter.');
	}
    // In case of View options selected, select Views - Currently not active
    if (module_exists('views')) {
      // Get a list of all views
      foreach (views_get_all_views() as $view => $viewdata) {
        $views_list[$viewdata->name] = $viewdata->name;
      }
      $form[$vocab->vid]['adv_taxonomy_menu_show_view'] = array(
        '#default_value'  => $settings->show_views,
        '#options'        => $views_list,
        '#title'          => t('Views available'),
        '#type'           => 'select',
      );
    }
    // General options
	$modules = array();
	foreach(module_implements('adv_taxonomy_menu_sql_alter') as $module) {
	  $modules[$module] = $module;
	}
	if(!empty($modules)) {
	  array_unshift($modules, 'none');
      $form['adv_taxonomy_menu_module_alter'] = array(
	    '#type' 			=> 'select',
        '#default_value'  => $settings->module_alter,
        '#options'        => $modules,
        '#title'          => t('Module to alter the SQL'),
        '#description'    => t('Modules with hook_adv_taxonomy_menu_alter. Select a module with which to alter the sql and reduce the number of nodes displayed according to custom requirements.'),
      );
	}
    $form['adv_taxonomy_menu_num_levels'] = array(
      '#value'    =>       t('The number of levels of this menu is currently set at '.$num_levels),
      '#type'           => 'markup',
    );
    $form['adv_taxonomy_menu_display_page'] = array(
      '#default_value'  => $settings->display_page,
      '#description'    => t('What is the label to use in the url? Example: categories/1/2/3, technology/1/2/3. Do not include a \'/\''),
      '#title'          => t('Module page'),
      '#type'           => 'textfield',
    );
    $form['adv_taxonomy_menu_display_num'] = array(
      '#default_value'  => $settings->display_num,
      '#description'    => t('If checked, number of node per term will be displayed in the menu.'),
      '#title'          => t('Display number of nodes per terms'),
      '#type'           => 'checkbox',
    );
    $form['adv_taxonomy_menu_hide_empty'] = array(
      '#default_value'  => $settings->hide_empty,
      '#description'    => t('If checked, only taxonomy terms with members will be shown in the menu.'),
      '#title'          => t('Hide Empty Terms'),
      '#type'           => 'checkbox',
    );
    $form['system_mid'] = array(
      '#value'    	  =>  $settings->mid,
      '#type'           => 'hidden',
    );
    $form['submit'] = array(
      '#value'          => t('Submit'),
      '#type'           => 'submit'
    );

    return $form;
  }
  else return array('message' => array('#type' => 'markup', '#value' => t('You need to create some vocabularies in order to use this menu system')));
}
}
/**
 * Admin area. validate form
 * 
 */
function _adv_taxonomy_menu_admin_validate(&$form, &$form_state) {
  if($form_state['values']['op']!= 'Delete') {
    if ($form_state['values']['adv_taxonomy_menu_name'] == '') {
      form_set_error('adv_taxonomy_menu_name', t('You must select a name for this menu system.'));
    }
    if ($form_state['values']['adv_taxonomy_menu_display_page'] == '') {
      form_set_error('adv_taxonomy_menu_display_page', t('You must select a label for the url.'));
    }
	//if (strpos($form_state['values']['adv_taxonomy_menu_display_page'], "/")) {
	if(!preg_match("/^[a-zA-Z0-9]+$/", $form_state['values']['adv_taxonomy_menu_display_page'])) {
	  form_set_error('adv_taxonomy_menu_display_page', t('Only alphanumeric characters are valid for a page label.'));
	}
  }
}
/**
 * Admin area. Configure the module, setting which
 * vocabularies will be converted into menu items
 */
function _adv_taxonomy_menu_admin_submit(&$form, &$form_state) {
  $order = array();
  foreach (taxonomy_get_vocabularies() as $vocab) {
    $order[$vocab->vid] = $form_state['values']['adv_taxonomy_menu_vocab_order_'. $vocab->vid];
  }
  $order = serialize($order);
  // either update or add depending on whether a tmid is supplied
  if($form['adv_taxonomy_menu_tmid']>0) {
	$mid = db_result(db_query("SELECT mlid FROM {menu_links} WHERE plid=0 AND link_path='' AND link_title = '%s'", $form_state['values']['adv_taxonomy_menu_name']));
    db_query("UPDATE {adv_taxonomy_menu} SET mid=%d, name='%s', display_page='%s', display_num=%d, hide_empty=%d, vocab_order='%s', show_normal='%s', show_views='%s', module_alter='%s' WHERE tmid=%d", $mid, $form_state['values']['adv_taxonomy_menu_name'], $form_state['values']['adv_taxonomy_menu_display_page'], $form_state['values']['adv_taxonomy_menu_display_num'], $form_state['values']['adv_taxonomy_menu_hide_empty'], $order, $form_state['values']['adv_taxonomy_menu_show'], $form_state['values']['adv_taxonomy_menu_show_view'], $form_state['values']['adv_taxonomy_menu_module_alter'], $form_state['values']['adv_taxonomy_menu_tmid']);
    drupal_set_message('Menu system updated successfully');
  }
  elseif(arg(3) == 'delete') {
    $tmid = arg(4);
    if($tmid>0) {
	  $name = db_result(db_query("SELECT name FROM {adv_taxonomy_menu} WHERE tmid=%d", $tmid));	
      $menu_name = 'menu-'.strtolower(str_replace(" ", "-", $name));
	  db_query("DELETE FROM {menu_custom} WHERE menu_name='%s'", $menu_name);
      db_query("DELETE FROM {adv_taxonomy_menu} WHERE tmid=%d", $tmid);
      drupal_set_message('Menu system deleted');
      //drupal_goto('admin/settings/adv_taxonomy_menu');
    }
  }
  else {
    // Create menu system and link to menu system
	$menu_name = strtolower(str_replace(" ", "-", $form_state['values']['adv_taxonomy_menu_name']));
    $item = array('values' => array('mlid' => 0, 'plid' => 0, 'path' => '', 'weight' => 0, 'type' => MENU_CUSTOM_MENU, 'enabled' => 1, 'menu_name' => $menu_name, 'title' => $form_state['values']['adv_taxonomy_menu_name'], 'description' => 'Advanced taxonomy menu'));
	include(drupal_get_path('module', 'menu').'/menu.admin.inc');
    menu_edit_menu_submit(array('#insert' => 1), $item);
	
	$mid = db_result(db_query("SELECT mlid FROM {menu_links} WHERE plid=0 AND link_path='' AND link_title = '%s'", $form_state['values']['adv_taxonomy_menu_name']));
    db_query("INSERT INTO {adv_taxonomy_menu} SET mid=%d, name='%s', display_page='%s', display_num=%d, hide_empty=%d, vocab_order='%s', show_normal='%s', show_views='%s', module_alter='%s'", $mid, $form_state['values']['adv_taxonomy_menu_name'], $form_state['values']['adv_taxonomy_menu_display_page'], $form_state['values']['adv_taxonomy_menu_display_num'], $form_state['values']['adv_taxonomy_menu_hide_empty'], $order, $form_state['values']['adv_taxonomy_menu_show'], $form_state['values']['adv_taxonomy_menu_show_view'], $form_state['values']['adv_taxonomy_menu_module_alter']);
    drupal_set_message('New menu system created');
  }
  // Rebuild the menu to include these features - Now done manually
  menu_rebuild();
  drupal_goto('admin/settings/adv_taxonomy_menu');
}

function adv_taxonomy_menu_delete_form($tmid) {
  $form['tmid'] = array('#type' => 'value', '#value' => $tmid);
  $form['form_id'] = array('#type' => 'value', '#value' => 'delete_menu');
   db_query("DELETE FROM {adv_taxonomy_menu} WHERE tmid=%d", $tmid);
   drupal_goto('admin/settings/adv_taxonomy_menu');
  return confirm_form(
   $form,
   t('Are you sure you want to delete this menu system'),
   isset($_GET['destination']) ? $_GET['destination'] : 'admin/settings/adv_taxonomy_menu',
   t('This action cannot be undone.'),
   t('Delete'), t('Cancel')
  );
}

function adv_taxonomy_menu_delete_form_submit(&$form, &$form_state) {
   db_query("DELETE FROM {adv_taxonomy_menu} WHERE tmid=%d", $form_state['values']['tmid']);
   drupal_goto('admin/settings/adv_taxonomy_menu');
}


/**
 * Generates the breadcumb for nodes that
 * have a category listed as a menu
 *
 * @param
 *   Object. The node object
 * @param
 *   Array. The list of all taxonomy vocabs and
 *   terms that this node have and are also
 *   menus
 */
function _adv_taxonomy_menu_node_view(&$node, &$vocabs) {
  foreach ($vocabs as $vid => $vocab) {
    $path = variable_get('adv_taxonomy_menu_display_page', 'category') .'/'. $vid;

    $tree = taxonomy_get_tree($vid);
    $old_depth = -1;
    $old_path = $path;

    // Generate the entire breadcumb
    foreach ($tree as $term) {
     if ($term->depth <= $old_depth) {
        $slashes_to_remove = $old_depth - $term->depth + 1;
        for ($i = 0; $i < $slashes_to_remove; $i++) {
          $old_path = substr($old_path, 0, strrpos($old_path, "/"));
        }
      }
      $path       = $old_path .'/'. $term->tid;
      $old_depth  = $term->depth;
      $old_path   = $path;

      // When we reach the term that this node uses,
      // set the breadcumb
      if ($term->tid == $vocab[0]) {
        menu_set_location(array(
          array('path' => $path, 'title' => t($term->name)),
          array('path' => 'node/'. $node->nid, 'title' => $node->title)
        ));

        // Quit after the first match.
        return;
      }
    }
  }
}

/**
 * Page callback that renders a node listing for the selected term.
 */
function _adv_taxonomy_menu_page() {
  // Check if the Vocabulary ID is set
  if ($vid = arg(1)) {
    if($result1 = adv_taxonomy_menu_get_settings($tmid)) {
      $settings = db_fetch_object($result1);
	}
    // Depending on what Output technique is used,
    // show the nodes' list
    if ($tid = arg(2)) {
      $tid = explode('/', $_GET['q']);
	  // first item is category page, second is vocab id.  Need all tids that follow
	  $tids = array();
	  foreach($tid as $key => $value) {
		if($key>1) $tids[] = $value;
	  }
	  // allow another module to modify the result set.  Note this will only process ONE module and then exit
	  if($settings->module_alter!='') {
        $function = $settings->module_alter .'_adv_taxonomy_menu_sql_alter';
		$result = $function($settings, $tids, 'and', variable_get('adv_taxonomy_menu_display_descendants', TRUE) ? 'all' : 0, 'sql');
	  }

      if(!isset($result)) $result = taxonomy_select_nodes($tids, 'and', variable_get('adv_taxonomy_menu_display_descendants', TRUE) ? 'all' : 0);
    }
    else {
      // If no arg(2), we're looking at just the vid. If
      //  grab depth 0 terms only.
      $tree = taxonomy_get_tree($vid);
      foreach ($tree as $term) {
        if ($term->depth == 0) {
          $tids[] = $term->tid;
        }
      }
	  // allow another module to modify the result set.  
	  if($settings->module_alter!='') {
        $function = $settings->module_alter .'_adv_taxonomy_menu_sql_alter';
		$result = $function($settings, $tids, 'or', 0, 'sql');
	  }
      // The requested terms have already been determined,
      // so don't request descendants here.
      if(!isset($result)) $result = taxonomy_select_nodes($tids, 'or', 0);
    }
    if ($settings->show_normal < 2) {
      // Render the selected nodes
	  $output = '';
	  if (isset($result)) {
	    $nodes = array();
		while ($node = db_fetch_object($result)) {
		  $nodes[] = $node;
	    }
        $output .= theme('adv_taxonomy_menu_output', $nodes);
        $output .= theme('pager', NULL, variable_get('default_nodes_main', 10), 0);
	  }
      // If no content found, return a "error" message
      return empty($output) ? t('No content for this category.') : $output;
    }
    else {
      // We will attempt to use the selected view
	  $nids = array();
	  if ($result) {
		while ($item = db_fetch_object($result)) {
		  $nids[] = $item->nid;
	     }
	  }
	  $view = views_get_view( $settings->show_views );
	  $view->is_cacheable = FALSE;
	  // find the filter which we created in taxonomy_menu_views_tables() and insert our values
	  foreach($view->display as $name => $parameters) {
	    foreach($parameters->display_options['filters'] as $key => $filter) {
		  
		  if($key == 'nid_range') {
		    $view->display[$name]->display_options['filters'][$key]['value'] = $nids;
		  }
		}
	  }
	  $view->is_cacheable = 0;
	  $output = $view->preview('default');
      $view->execute('default');
	  return $output;
    }
  }
}

function theme_adv_taxonomy_menu_output($nodes) {
  $output = '<ul class="item-list">';
  foreach($nodes as $node) {
    $output .= '<li>'.l($node->title, 'node/'.$node->nid).'</li>';
  
  }
  $output .= '</ul>';
  return $output;
}